﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Manul.Interface;
using Manul.Genetics;
using Manul.Interface.TreeNodes;
using Manul.Genetics.Genom;
using Manul.Genetics.Character;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;
using Manul.Genetics.Compiler;
using Manul.GenomCreationTest.StringConstants;

namespace Manul.GenomCreationTest
{
    public partial class FormGenomConfig : Form
    {
        public FormGenomConfig()
        {
            InitializeComponent();
            CurrentWindow = new Win32Window(this);
            AppMessages = new AppMessages(CurrentWindow);
            comboBoxLocusPosition.DataSource = System.Enum.GetValues(typeof(LocusPlaceType));
            comboBoxLocusPosition.SelectedItem = LocusPlaceType.XY;
            dataGridCharacterParams.AutoGenerateColumns = false;
        }

        private Win32Window CurrentWindow = null;
        private AppMessages AppMessages = null;

        private GenomData GenomDataItem = new GenomData();

        private void FormMain_Load(object sender, EventArgs e)
        {
            SetFileNameTitle(String.Empty);
        }

        private void AddAsChild(TreeView treeView, TreeNode newNode)
        {
            if (treeView.SelectedNode != null)
                treeView.SelectedNode.Nodes.Add(newNode);
            else
                treeView.Nodes.Add(newNode);
            treeView.SelectedNode = newNode;
        }

        private void buttonDeleteGenomDirectory_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
            {
                if (treeViewGens.SelectedNode.Parent != null)
                    (treeViewGens.SelectedNode.Parent as ObjectTreeNode<GenomDirectory>).Obj.GenomItems.Remove((treeViewGens.SelectedNode as ObjectTreeNode<GenomDirectory>).Obj);
                else
                    GenomDataItem.GenomValues.GenomItems.Remove((treeViewGens.SelectedNode as ObjectTreeNode<GenomDirectory>).Obj);
                treeViewGens.Nodes.Remove(treeViewGens.SelectedNode);
            }
        }

        private void buttonAddGenomDirectory_Click(object sender, EventArgs e)
        {
            DoPreSave();
            ObjectTreeNode<GenomDirectory> newNode = new ObjectTreeNode<GenomDirectory>();
            newNode.Name = String.Empty;
            newNode.ImageKey = ListViewIndexes.GenomDirectory;
            newNode.SelectedImageKey = ListViewIndexes.GenomDirectory_Selected;
            if (treeViewGens.SelectedNode != null)
            {
                if (treeViewGens.SelectedNode is ObjectTreeNode<GenomDirectory>)
                {
                    (treeViewGens.SelectedNode as ObjectTreeNode<GenomDirectory>).Obj.GenomItems.Add(newNode.Obj);
                    treeViewGens.SelectedNode.Nodes.Add(newNode);
                    treeViewGens.SelectedNode = newNode;
                }
                else if (treeViewGens.SelectedNode.Parent == null)
                {
                    GenomDataItem.GenomValues.GenomItems.Add(newNode.Obj);
                    treeViewGens.Nodes.Add(newNode);
                    treeViewGens.SelectedNode = newNode;
                }
                else if (treeViewGens.SelectedNode.Parent is ObjectTreeNode<GenomDirectory>)
                {
                    (treeViewGens.SelectedNode.Parent as ObjectTreeNode<GenomDirectory>).Obj.GenomItems.Add(newNode.Obj);
                    treeViewGens.SelectedNode.Parent.Nodes.Add(newNode);
                    treeViewGens.SelectedNode = newNode;
                }
            }
            else
            {
                GenomDataItem.GenomValues.GenomItems.Add(newNode.Obj);
                treeViewGens.Nodes.Add(newNode);
                treeViewGens.SelectedNode = newNode;
            }
        }

        private void buttonAddLocus_Click(object sender, EventArgs e)
        {
            DoPreSave();
            ObjectTreeNode<Locus> newNode = new ObjectTreeNode<Locus>();
            newNode.Name = String.Empty;
            newNode.ImageKey = ListViewIndexes.Locus;
            newNode.SelectedImageKey = ListViewIndexes.Locus_Selected;
            if (treeViewGens.SelectedNode != null)
            {
                if (treeViewGens.SelectedNode is ObjectTreeNode<GenomDirectory>)
                {
                    (treeViewGens.SelectedNode as ObjectTreeNode<GenomDirectory>).Obj.GenomItems.Add(newNode.Obj);
                    AddAsChild(treeViewGens, newNode);
                }
                else if (treeViewGens.SelectedNode.Parent == null)
                {
                    GenomDataItem.GenomValues.GenomItems.Add(newNode.Obj);
                    treeViewGens.Nodes.Add(newNode);
                    treeViewGens.SelectedNode = newNode;
                }
                else if (treeViewGens.SelectedNode.Parent != null && treeViewGens.SelectedNode.Parent is ObjectTreeNode<GenomDirectory>)
                {
                    (treeViewGens.SelectedNode.Parent as ObjectTreeNode<GenomDirectory>).Obj.GenomItems.Add(newNode.Obj);
                    treeViewGens.SelectedNode.Parent.Nodes.Add(newNode);
                    treeViewGens.SelectedNode = newNode;
                }
            }
            else
            {
                GenomDataItem.GenomValues.GenomItems.Add(newNode.Obj);
                AddAsChild(treeViewGens, newNode);
            }
        }

        private void treeViewGenes_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node != null)
            {
                if (e.Node is ObjectTreeNode<GenomDirectory>)
                {
                    buttonAddGenomDirectory.Enabled = true;
                    buttonAddLocus.Enabled = true;
                    buttonAddGen.Enabled = false;

                    groupBoxGenomDirectory.Visible = true;
                    groupBoxLocus.Visible = false;
                    groupBoxGen.Visible = false;

                    groupBoxGenomDirectory.Parent = groupBoxRightPanel;
                    groupBoxLocus.Parent = this;
                    groupBoxGen.Parent = this;
                    groupBoxGenomDirectory.Dock = DockStyle.Bottom;

                    ObjectTreeNode<GenomDirectory> item = e.Node as ObjectTreeNode<GenomDirectory>;
                    textBoxGenomDirectoryName.Text = item.Obj.Name;
                    textBoxGenomDirectoryDescription.Text = item.Obj.Description;

                    textBoxGenomDirectoryName.Focus();
                }
                else if (e.Node is ObjectTreeNode<Locus>)
                {
                    buttonAddGenomDirectory.Enabled = true;
                    buttonAddLocus.Enabled = true;
                    buttonAddGen.Enabled = true;

                    groupBoxGenomDirectory.Visible = false;
                    groupBoxLocus.Visible = true;
                    groupBoxGen.Visible = false;

                    groupBoxGenomDirectory.Parent = this;
                    groupBoxLocus.Parent = groupBoxRightPanel;
                    groupBoxGen.Parent = this;
                    groupBoxLocus.Dock = DockStyle.Bottom;

                    ObjectTreeNode<Locus> item = e.Node as ObjectTreeNode<Locus>;
                    textBoxLocusName.Text = item.Obj.Name;
                    textBoxLocusDescription.Text = item.Obj.Description;
                    numericLocusCapacity.Value = item.Obj.Capacity;
                    comboBoxLocusPosition.SelectedItem = item.Obj.PlaceType;

                    textBoxLocusName.Focus();
                }
                else if (e.Node is ObjectTreeNode<Gen>)
                {
                    buttonAddGenomDirectory.Enabled = false;
                    buttonAddLocus.Enabled = false;
                    buttonAddGen.Enabled = true;

                    groupBoxGenomDirectory.Visible = false;
                    groupBoxLocus.Visible = false;
                    groupBoxGen.Visible = true;

                    groupBoxGenomDirectory.Parent = this;
                    groupBoxLocus.Parent = this;
                    groupBoxGen.Parent = groupBoxRightPanel;
                    groupBoxGen.Dock = DockStyle.Bottom;

                    ObjectTreeNode<Gen> item = e.Node as ObjectTreeNode<Gen>;
                    textBoxGenName.Text = item.Obj.Name;
                    textBoxGenDescription.Text = item.Obj.Description;
                    numericGenDomenance.Value = item.Obj.DominantLevel;
                    textBoxGenCode.Text = item.Obj.Code;

                    textBoxGenName.Focus();
                }
            }
            else
            {
                buttonAddGenomDirectory.Enabled = true;
                buttonAddLocus.Enabled = true;
                buttonAddGen.Enabled = false;
            }
        }

        private void buttonSaveGenomDirectory_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
            {
                ObjectTreeNode<GenomDirectory> newNode = treeViewGens.SelectedNode as ObjectTreeNode<GenomDirectory>;
                newNode.Name = textBoxGenomDirectoryName.Text;
                newNode.Text = textBoxGenomDirectoryName.Text;
                newNode.Obj.Name = textBoxGenomDirectoryName.Text;
                newNode.Obj.Description = textBoxGenomDirectoryDescription.Text;
            }
        }

        private void buttonSaveLocus_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
            {
                ObjectTreeNode<Locus> newNode = treeViewGens.SelectedNode as ObjectTreeNode<Locus>;
                newNode.Name = textBoxLocusName.Text;
                newNode.Text = textBoxLocusName.Text;
                newNode.Obj.Name = textBoxLocusName.Text;
                newNode.Obj.Description = textBoxLocusDescription.Text;
                newNode.Obj.PlaceType = (LocusPlaceType)comboBoxLocusPosition.SelectedValue;
                newNode.Obj.Capacity = (int)numericLocusCapacity.Value;
            }
        }

        private void buttonSaveGen_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
            {
                ObjectTreeNode<Gen> newNode = treeViewGens.SelectedNode as ObjectTreeNode<Gen>;
                newNode.Name = textBoxGenName.Text;
                newNode.Text = textBoxGenName.Text;
                newNode.Obj.Name = textBoxGenName.Text;
                newNode.Obj.Description = textBoxGenDescription.Text;
                newNode.Obj.DominantLevel = (int)numericGenDomenance.Value;
                newNode.Obj.Code = textBoxGenCode.Text;
            }
        }

        private void buttonAddGen_Click(object sender, EventArgs e)
        {
            DoPreSave();
            if (treeViewGens.SelectedNode != null)
            {

                ObjectTreeNode<Gen> newNode = new ObjectTreeNode<Gen>();
                newNode.Name = String.Empty;
                newNode.ImageKey = ListViewIndexes.Gen;
                newNode.SelectedImageKey = ListViewIndexes.Gen_Selected;
                newNode.Name = String.Empty;
                if (treeViewGens.SelectedNode is ObjectTreeNode<Locus>)
                {
                    (treeViewGens.SelectedNode as ObjectTreeNode<Locus>).Obj.Gens.Add(newNode.Obj);
                    AddAsChild(treeViewGens, newNode);
                }
                else if (treeViewGens.SelectedNode.Parent != null && treeViewGens.SelectedNode.Parent is ObjectTreeNode<Locus>)
                {
                    (treeViewGens.SelectedNode.Parent as ObjectTreeNode<Locus>).Obj.Gens.Add(newNode.Obj);
                    treeViewGens.SelectedNode.Parent.Nodes.Add(newNode);
                    treeViewGens.SelectedNode = newNode;
                }
            }
        }

        private void textBoxGenomDirectoryName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                buttonSaveGenomDirectory_Click(textBoxGenomDirectoryName, new EventArgs());
                e.SuppressKeyPress = true;
                e.Handled = true;
                textBoxGenomDirectoryDescription.Focus();
            }
        }

        private void textBoxLocusName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                buttonSaveLocus_Click(textBoxLocusName, new EventArgs());
                e.SuppressKeyPress = true;
                e.Handled = true;
                textBoxLocusDescription.Focus();
            }
        }

        private void textBoxGenName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                buttonSaveGen_Click(textBoxGenName, new EventArgs());
                e.SuppressKeyPress = true;
                e.Handled = true;
                textBoxGenDescription.Focus();
            }
        }

        private void DoPreSave()
        {
            if (groupBoxGenomDirectory.Visible)
                buttonSaveGenomDirectory_Click(groupBoxGenomDirectory, new EventArgs());
            if (groupBoxLocus.Visible)
                buttonSaveLocus_Click(groupBoxLocus, new EventArgs());
            if (groupBoxGen.Visible)
                buttonSaveGen_Click(groupBoxGen, new EventArgs());
            if (groupBoxCharactersDirectory.Visible)
                buttonSaveCharacterDirectory_Click(groupBoxCharactersDirectory, new EventArgs());
            if (groupBoxCharacter.Visible)
                buttonSaveCharacter_Click(groupBoxCharactersDirectory, new EventArgs());
        }

        private void buttonDeleteGen_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
            {
                if (treeViewGens.SelectedNode.Parent != null)
                    (treeViewGens.SelectedNode.Parent as ObjectTreeNode<Locus>).Obj.Gens.Remove((treeViewGens.SelectedNode as ObjectTreeNode<Gen>).Obj);
                treeViewGens.Nodes.Remove(treeViewGens.SelectedNode);
            }
        }

        private void buttonDeleteLocus_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
            {
                if (treeViewGens.SelectedNode.Parent != null)
                    (treeViewGens.SelectedNode.Parent as ObjectTreeNode<GenomDirectory>).Obj.GenomItems.Remove((treeViewGens.SelectedNode as ObjectTreeNode<Locus>).Obj);
                else
                    GenomDataItem.GenomValues.GenomItems.Remove((treeViewGens.SelectedNode as ObjectTreeNode<Locus>).Obj);
                treeViewGens.Nodes.Remove(treeViewGens.SelectedNode);
            }
        }

        private void buttonGensUp_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
                treeViewGens.SelectedNode.MoveUp();
            if (treeViewGens.SelectedNode.Parent != null)
                treeViewGens.SelectedNode.MoveUp(GenomDataItem.GenomValues);
        }

        private void buttonGensDown_Click(object sender, EventArgs e)
        {
            if (treeViewGens.SelectedNode != null)
                treeViewGens.SelectedNode.MoveDown();
            if (treeViewGens.SelectedNode.Parent != null)
                treeViewGens.SelectedNode.MoveDown(GenomDataItem.GenomValues);
        }

        private void buttonAddRootGenomDirectory_Click(object sender, EventArgs e)
        {
            DoPreSave();
            treeViewGens.SelectedNode = null;
            buttonAddGenomDirectory_Click(sender, e);
        }

        private void buttonAddCharacterDirectory_Click(object sender, EventArgs e)
        {
            DoPreSave();
            ObjectTreeNode<CharacterDirectory> newNode = new ObjectTreeNode<CharacterDirectory>();
            newNode.Name = String.Empty;
            newNode.ImageKey = ListViewIndexes.GenomDirectory;
            newNode.SelectedImageKey = ListViewIndexes.GenomDirectory_Selected;
            if (treeViewCharacter.SelectedNode != null && treeViewCharacter.SelectedNode is ObjectTreeNode<CharacterDirectory>)
            {
                (treeViewCharacter.SelectedNode as ObjectTreeNode<CharacterDirectory>).Obj.Characters.Add(newNode.Obj);
                treeViewCharacter.SelectedNode.Nodes.Add(newNode);
                treeViewCharacter.SelectedNode = newNode;
            }
            else
            {
                GenomDataItem.CharacterValues.Add(newNode.Obj);
                treeViewCharacter.Nodes.Add(newNode);
                treeViewCharacter.SelectedNode = newNode;
            }
        }

        private void buttonSaveCharacterDirectory_Click(object sender, EventArgs e)
        {
            if (treeViewCharacter.SelectedNode != null)
            {
                ObjectTreeNode<CharacterDirectory> newNode = treeViewCharacter.SelectedNode as ObjectTreeNode<CharacterDirectory>;
                newNode.Name = textBoxCharacterDirectoryName.Text;
                newNode.Text = textBoxCharacterDirectoryName.Text;
                newNode.Obj.Name = textBoxCharacterDirectoryName.Text;
                newNode.Obj.Description = textBoxCharacterDirectoryDescription.Text;
            }
        }

        private void treeViewCharacter_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node != null)
            {
                if (e.Node is ObjectTreeNode<CharacterDirectory>)
                {
                    groupBoxCharactersDirectory.Visible = true;
                    groupBoxCharacter.Visible = false;
                    groupBoxCharactersDirectory.Parent = groupBoxCharacterRight;
                    groupBoxCharactersDirectory.Dock = DockStyle.Bottom;

                    ObjectTreeNode<CharacterDirectory> item = e.Node as ObjectTreeNode<CharacterDirectory>;
                    textBoxCharacterDirectoryName.Text = item.Obj.Name;
                    textBoxCharacterDirectoryDescription.Text = item.Obj.Description;

                    panelCompiledCharacter.Visible = false;

                    textBoxCharacterDirectoryName.Focus();
                }
                else if (e.Node is ObjectTreeNode<Character>)
                {
                    groupBoxCharactersDirectory.Visible = false;
                    groupBoxCharacter.Visible = true;
                    groupBoxCharacter.Parent = groupBoxCharacterRight;
                    groupBoxCharacter.Dock = DockStyle.Bottom;

                    ObjectTreeNode<Character> item = e.Node as ObjectTreeNode<Character>;
                    textBoxCharacterName.Text = item.Obj.Name;
                    textBoxCharacterDescription.Text = item.Obj.Description;
                    textBoxCharacterCode.Text = item.Obj.Code;
                    checkBoxCharacterIsLethal.Checked = item.Obj.IsLethal;

                    panelCompiledCharacter.Visible = true;

                    dataGridCharacterParams.DataSource = item.Obj.Params;

                    LoadEpistasis(item.Obj);

                    PrepareErrorLayout();
                    foreach (GenomCompilationError err in item.Obj.CompilationErrors)
                        ShowError(err);

                    textBoxCharacterName.Focus();
                }
            }
            else
            {
                buttonAddCharacterDirectory.Enabled = true;
                buttonAddRootCharacterDirectory.Enabled = true;
                buttonAddCharacterDirectory.Enabled = false;
            }
        }

        private void buttonAddRootCharacterDirectory_Click(object sender, EventArgs e)
        {
            DoPreSave();
            treeViewCharacter.SelectedNode = null;
            buttonAddCharacterDirectory_Click(sender, e);
        }

        private void buttonAddCharacter_Click(object sender, EventArgs e)
        {
            DoPreSave();
            ObjectTreeNode<Character> newNode = new ObjectTreeNode<Character>();
            newNode.Name = String.Empty;
            newNode.ImageKey = ListViewIndexes.Character;
            newNode.SelectedImageKey = ListViewIndexes.Character_Selected;
            newNode.Name = String.Empty;
            if (treeViewCharacter.SelectedNode != null)
            {

                if (treeViewCharacter.SelectedNode is ObjectTreeNode<CharacterDirectory>)
                {
                    (treeViewCharacter.SelectedNode as ObjectTreeNode<CharacterDirectory>).Obj.Characters.Add(newNode.Obj);
                    AddAsChild(treeViewCharacter, newNode);
                }
                else if (treeViewCharacter.SelectedNode.Parent != null && treeViewCharacter.SelectedNode.Parent is ObjectTreeNode<CharacterDirectory>)
                {
                    (treeViewCharacter.SelectedNode.Parent as ObjectTreeNode<CharacterDirectory>).Obj.Characters.Add(newNode.Obj);
                    treeViewCharacter.SelectedNode.Parent.Nodes.Add(newNode);
                    treeViewCharacter.SelectedNode = newNode;
                }
            }
            else
            {
                GenomDataItem.CharacterValues.Add(newNode.Obj);
                treeViewCharacter.Nodes.Add(newNode);
                treeViewCharacter.SelectedNode = newNode;
            }
        }

        private void buttonDeleteCharacterDirectory_Click(object sender, EventArgs e)
        {
            if (treeViewCharacter.SelectedNode != null)
            {
                if (treeViewCharacter.SelectedNode.Parent != null)
                    (treeViewCharacter.SelectedNode.Parent as ObjectTreeNode<CharacterDirectory>).Obj.Characters.Remove((treeViewCharacter.SelectedNode as ObjectTreeNode<CharacterDirectory>).Obj);
                else
                    GenomDataItem.CharacterValues.Characters.Remove((treeViewCharacter.SelectedNode as ObjectTreeNode<CharacterDirectory>).Obj);
                treeViewCharacter.Nodes.Remove(treeViewCharacter.SelectedNode);
            }
        }

        private void buttonCharacterDelete_Click(object sender, EventArgs e)
        {
            if (treeViewCharacter.SelectedNode != null)
            {
                if (treeViewCharacter.SelectedNode.Parent != null)
                    (treeViewCharacter.SelectedNode.Parent as ObjectTreeNode<CharacterDirectory>).Obj.Characters.Remove((treeViewCharacter.SelectedNode as ObjectTreeNode<Character>).Obj);
                treeViewCharacter.Nodes.Remove(treeViewCharacter.SelectedNode);
            }
        }

        private void buttonSaveCharacter_Click(object sender, EventArgs e)
        {
            if (treeViewCharacter.SelectedNode != null)
            {
                ObjectTreeNode<Character> newNode = treeViewCharacter.SelectedNode as ObjectTreeNode<Character>;
                newNode.Name = textBoxCharacterName.Text;
                newNode.Text = textBoxCharacterName.Text;
                newNode.Obj.Name = textBoxCharacterName.Text;
                newNode.Obj.Description = textBoxCharacterDescription.Text;
                newNode.Obj.Code = textBoxCharacterCode.Text;
                newNode.Obj.IsLethal = checkBoxCharacterIsLethal.Checked;

                PrepareErrorLayout();

                Compile(newNode as ObjectTreeNode<Character>);
            }
        }
        private void PrepareErrorLayout()
        {
            listViewCharacterCompiled.Items.Clear();
        }
        private void Compile(ObjectTreeNode<Character> node)
        {
            node.Obj.CompilationErrors.Clear();
            List<CompilationResult> compilationResults = GenomCompiler.Compile(GenomDataItem, node.Obj);
            if (!node.Obj.IsCompiled)
            {
                node.ImageKey = ListViewIndexes.Character_Error;
                node.SelectedImageKey = ListViewIndexes.Character_Error_Selected;
            }
            else
            {
                node.ImageKey = ListViewIndexes.Character;
                node.SelectedImageKey = ListViewIndexes.Character_Selected;
            }
            foreach (CompilationResult compilationResult in compilationResults)
            {
                if (compilationResult.IsSuccessfull)
                {
                    ShowGen(compilationResult.GenItem);
                }
                else
                {
                    ShowError(compilationResult.Error);
                    node.Obj.CompilationErrors.Add(compilationResult.Error);
                }
            }
        }
        private void ShowGen(Gen gen)
        {
            ListViewItem newNode = new ListViewItem(String.Format("{0} [{1}]", gen.Name, gen.Code));
            newNode.ImageKey = ListViewIndexes.Character_Log;
            listViewCharacterCompiled.Items.Add(newNode);
        }
        private void ShowError(GenomCompilationError error)
        {
            if (error.CompilationErrorType == GenomCompilationErrorType.None)
                return;
            ListViewItem newNode = new ListViewItem(error.ErrorMessage);
            switch (error.CompilationErrorType)
            {
                default:
                    newNode.ImageKey = ListViewIndexes.Character_Log_Error;
                    break;
            }
            listViewCharacterCompiled.Items.Add(newNode);
        }

        private void textBoxCharacterDirectoryName_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                buttonSaveCharacterDirectory_Click(textBoxGenomDirectoryName, new EventArgs());
                e.SuppressKeyPress = true;
                e.Handled = true;
                textBoxGenomDirectoryDescription.Focus();
            }
        }

        private void textBoxCharacterName_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                buttonSaveCharacter_Click(textBoxCharacterName, new EventArgs());
                e.SuppressKeyPress = true;
                e.Handled = true;
                textBoxCharacterDescription.Focus();
            }
        }

        private void buttonCharactersUp_Click(object sender, EventArgs e)
        {
            if (treeViewCharacter.SelectedNode != null)
                treeViewCharacter.SelectedNode.MoveUp();
            if (treeViewCharacter.SelectedNode.Parent != null)
                treeViewCharacter.SelectedNode.MoveUp(GenomDataItem.CharacterValues);
        }

        private void buttonbuttonCharactersDown_Click(object sender, EventArgs e)
        {
            if (treeViewCharacter.SelectedNode != null)
                treeViewCharacter.SelectedNode.MoveDown();
            if (treeViewCharacter.SelectedNode.Parent != null)
                treeViewCharacter.SelectedNode.MoveDown(GenomDataItem.CharacterValues);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private string ProfileFileName = String.Empty;

        private string FileName
        {
            get
            {
                return ProfileFileName;
            }
            set
            {
                ProfileFileName = value;
                SetFileNameTitle(value);
            }
        }

        private void SetFileNameTitle(String fileName)
        {
            AssemblyName currentAssemblyName = Assembly.GetExecutingAssembly().GetName();
            if (fileName == String.Empty)
                this.Text = String.Format("{0} {1}", CurrentAssemblyInfo.CurrentAssemblyInfo.Title, CurrentAssemblyInfo.CurrentAssemblyInfo.ShortVersion);
            else
                this.Text = String.Format("{0} {1} - {2}", CurrentAssemblyInfo.CurrentAssemblyInfo.Title, CurrentAssemblyInfo.CurrentAssemblyInfo.ShortVersion, fileName);
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (FileName == String.Empty)
                saveAsToolStripMenuItem_Click(sender, e);
            else
                this.SaveFile(FileName);
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                FileName = saveFileDialog.FileName;
                this.SaveFile(FileName);
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                LoadFile(openFileDialog.FileName);
                // CompileAll();
            }
        }

        public void LoadFile(String fileName)
        {
            try
            {
                FileName = fileName;
                this.GenomDataItem = IO.OpenFromXml(this.FileName);
            }
            catch (InvalidOperationException ex)
            {
                AppMessages.ShowError(ex.Message);
            }
            if (this.GenomDataItem != null)
            {
                Clear();
                treeViewGens.LoadGens(this.GenomDataItem.GenomValues);
                treeViewCharacter.LoadCharacters(this.GenomDataItem.CharacterValues);
            }
            else
            {
                FileName = String.Empty;
            }
        }
        public void SaveFile(String fileName)
        {
            IO.SaveToXml(this.GenomDataItem, FileName);
        }
        public void Clear()
        {
            treeViewGens.Nodes.Clear();
            treeViewCharacter.Nodes.Clear();
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.FileName = String.Empty;
            this.GenomDataItem.Dispose();
            this.Clear();
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (AboutBoxGenom aboutBoxGenom = new AboutBoxGenom())
                aboutBoxGenom.ShowDialog();
        }

        private void buttonCharacterEpistasisAdd_Click(object sender, EventArgs e)
        {
            using (FormEpistasis formEpistasis = new FormEpistasis())
            {
                Character activeCharacter = SelectedCharacter;
                formEpistasis.CurrentCharacter = activeCharacter;
                formEpistasis.CurrentCharacters = this.GenomDataItem.CharacterValues;
                if (formEpistasis.ShowDialog(this) == DialogResult.OK)
                {
                    activeCharacter.Epistasis.Clear();
                    PrepareErrorLayout();
                    foreach (Character character in formEpistasis.CurrentEpistasis)
                    {
                        if (!activeCharacter.Epistasis.Contains(character) && character != activeCharacter)
                        {
                            GenomCompilationError error = GenomCompiler.CheckEpistasisLoop(activeCharacter, character);
                            if (error == GenomCompilationError.Null)
                                activeCharacter.Epistasis.Add(character);
                            else
                                ShowError(error);
                        }
                    }
                    activeCharacter.UpdateEpistasisGuid();
                    LoadEpistasis(activeCharacter);
                }
            }
        }

        private void LoadEpistasis(Character activeCharacter)
        {
            listViewCharacterEpistasis.Items.Clear();
            foreach (Character characterEpistatic in activeCharacter.Epistasis)
            {
                ListViewItem listViewItemCharacter = new ListViewItem(characterEpistatic.Name);
                listViewItemCharacter.ImageKey = ListViewIndexes.Character;
                listViewItemCharacter.SubItems.Add(characterEpistatic.GUID);
                listViewCharacterEpistasis.Items.Add(listViewItemCharacter);
            }
        }

        public Character SelectedCharacter
        {
            get
            {
                if (treeViewCharacter.SelectedNode != null && treeViewCharacter.SelectedNode is ObjectTreeNode<Character>)
                    return (treeViewCharacter.SelectedNode as ObjectTreeNode<Character>).Obj;
                return null;
            }
        }

        private void buttonCharacterEpistasisDelete_Click(object sender, EventArgs e)
        {
            foreach(ListViewItem item in listViewCharacterEpistasis.SelectedItems)
            {
                List<Character> Epistasis = SelectedCharacter.Epistasis;
                List<String> EpistasisGuid = SelectedCharacter.EpistasisGuid;
                int i = 0;
                while (i < Epistasis.Count)
                {
                    if (Epistasis[i].GUID == item.SubItems[1].Text)
                    {
                        Epistasis.RemoveAt(i);
                        EpistasisGuid.RemoveAt(i);
                    }
                    i++;
                }
                listViewCharacterEpistasis.Items.Remove(item);
            }
        }

        private void listViewCharacterCompiled_Resize(object sender, EventArgs e)
        {
            listViewCharacterCompiledTextColumn.Width = listViewCharacterCompiled.Width - 30;
        }

        private void compileAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CompileAll();
        }
        private void CompileAll()
        {
            List<TreeNode> treeNodes = new List<TreeNode>();
            foreach (TreeNode treeNode in treeViewCharacter.Nodes)
                treeNodes.Add(treeNode);
            int i = 0;
            PrepareErrorLayout();
            while (i < treeNodes.Count)
            {
                foreach (TreeNode treeNode in treeNodes[i].Nodes)
                    treeNodes.Add(treeNode);
                if (treeNodes[i] is ObjectTreeNode<Character>)
                    Compile(treeNodes[i] as ObjectTreeNode<Character>);
                i++;
            }
        }
    }
}
